package thinkinjava4.ch21_concurrency.waxomatic;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static thinkinjava4.util.Print.print;
import static thinkinjava4.util.Print.printnb;

class Car {
    private boolean waxOn = false;

    public synchronized void waxed() {
        waxOn = true;//Ready to buff
        notifyAll();
    }

    public synchronized void buffed() {
        waxOn = false;
        notifyAll();
    }

    public synchronized void waitForWaxing() throws InterruptedException {
        while (!waxOn) wait();
    }

    public synchronized void waitForBuffing() throws InterruptedException {
        while (waxOn) wait();
    }
}

/**
 * 打蜡
 */
class WaxOn implements Runnable {
    private Car car;

    public WaxOn(Car c) {
        car = c;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                printnb("Wa on! ");
                TimeUnit.MILLISECONDS.sleep(200);
                car.waxed();//打蜡完成
                car.waitForBuffing();//等待抛光处理
            }
        } catch (InterruptedException e) {
            print("Exiting via interrupt");
        }
        print("Ending Wax On task");
    }
}

class WaxOff implements Runnable {
    private Car car;

    public WaxOff(Car c) {
        car = c;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                car.waitForWaxing();//等待打蜡完成
                printnb("Wax Off! ");
                //开始抛光处理
                TimeUnit.MILLISECONDS.sleep(200);
                car.buffed();//抛光处理完成
            }
        } catch (InterruptedException e) {
            print("Exiting via interrupt");
        }
        print("Ending Wax Off task");
    }
}

/**
 * 汽车 上蜡抛光上蜡抛光上蜡抛光...
 */
public class WaxOMatic {
    public static void main(String[] args) throws Exception {
        Car car = new Car();
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(new WaxOff(car));
        exec.execute(new WaxOn(car));
        TimeUnit.SECONDS.sleep(5);
        exec.shutdownNow();
    }
}
